package ru.ifmo.metopt;

import org.springframework.beans.factory.annotation.Required;
import ru.ifmo.metopt.abstracts.Function1D;
import ru.ifmo.metopt.abstracts.SingleDimensionSolver;

/**
 * @author avhaliullin
 */
public class FibonacciSolver implements SingleDimensionSolver {
    private static final double GOLDEN_RATION_PROPORTION = (1 + Math.pow(5, 0.5)) / 2;
    private double stopDx;
    private double indeterminacyInterval;

    private double leftPoint(double a, double b) {
        return b - (b - a) / GOLDEN_RATION_PROPORTION;
    }

    private double rightPoint(double a, double b) {
        return a + (b - a) / GOLDEN_RATION_PROPORTION;
    }

    //a---c--d---b
    @Override
    public double solve(Function1D f) {
        double a = 0;
        double b = indeterminacyInterval;
        double c = leftPoint(a, b);
        double d = rightPoint(a, b);

        double fc = f.f(c);
        double fd = f.f(d);

        while (b - a > stopDx) {
            if (fc > fd) {
                a = c;
                c = d;
                d = rightPoint(a, b);

                fc = fd;
                fd = f.f(d);
            } else {
                b = d;
                d = c;
                c = leftPoint(a, b);

                fd = fc;
                fc = f.f(c);
            }
        }
        return fc < fd ? c : d;
    }

    @Required
    public void setStopDx(double stopDx) {
        this.stopDx = stopDx;
    }

    @Required
    public void setIndeterminacyInterval(double indeterminacyInterval) {
        this.indeterminacyInterval = indeterminacyInterval;
    }
}
